package com.strategy.demo04;

import org.junit.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class TestEmpDao {
    List<Emp> emps = Arrays.asList(
            new Emp("ww", 20, 2222.0),
            new Emp("ls", 30, 3333.0),
            new Emp("zs", 35, 5555.0),
            new Emp("zl", 40, 4444.0),
            new Emp("tq", 56, 6666.0)
    );

    /**
     * 测试业务方法及接口优化业务方法测试
     */
    @Test
    public void testEmpByCondition(){
        List<Emp> newEmps = null;
        //1、测试业务方法1
        newEmps = this.filterEmpByAge(emps);

        //2、测试业务方法2
        newEmps = this.filterEmpByAge2(emps);

        //3、测试业务方法3
        newEmps = this.filterEmpBySalary(emps);

        //4、测试优化业务方法4
//        newEmps = this.filterEmp(emps, new EmpFilterByAge());
//        newEmps = this.filterEmp(emps, new EmpFilterByAge2());
        newEmps = this.filterEmp(emps, new EmpFilterBySalary());

        for (Emp newEmp : newEmps) {
            System.out.println(newEmp);
        }
    }


    /**
     * 业务方法1：过滤员工年龄>=35的员工
     * @param empList 待过滤的Emp集合
     * @return 返回过滤后的集合
     */
    public List<Emp> filterEmpByAge(List<Emp> empList){
        List<Emp> newEmpList = new ArrayList<>();
        for (Emp emp : empList) {
            if (emp.getAge() >= 35) {
                newEmpList.add(emp);
            }
        }
        return newEmpList;
    }

    /**
     * 业务方法2：过滤员工年龄小于35的员工
     */
    public List<Emp> filterEmpByAge2(List<Emp> empList){
        List<Emp> newEmpList = new ArrayList<>();

        for (Emp emp : empList) {
            if(emp.getAge()<35){
                newEmpList.add(emp);
            }
        }
        return newEmpList;
    }

    /**
     * 业务方法3：过滤员工工资高于5000的。
     */
    public List<Emp> filterEmpBySalary(List<Emp> empList){
        List<Emp> newEmpList = new ArrayList<>();
        for (Emp emp : empList) {
            if (emp.getSalary() > 5000) {
                newEmpList.add(emp);
            }
        }
        return newEmpList;
    }

    /**
     * 业务方法4：采用策略模式优化业务方法
     * 对于上面不同业务方法，可能仅仅只有if (emp.getAge() < 35) 一行代码区别。
     * 针对于此，采用策略模式进行改造。改造后，通过统一调用策略中方法进行判断 if(filter.test(emp))即可。
     * 对于业务方法1、2、3可以通过只需定义一个业务方法4就可搞定。
     *
     * @param empList 待过滤的 Emp 集合
     * @param filter 过滤策略
     * @return 返回过滤后的集合
     */
    public List<Emp> filterEmp(List<Emp> empList, EmpFilterInterface<Emp> filter){
        List<Emp> newEmpList = new ArrayList<>();
        for (Emp emp : empList) {
            if(filter.test(emp)){
                newEmpList.add(emp);
            }
        }
        return newEmpList;
    }

    /**
     * 测试业务方法：通过匿名内部类优化(策略模式：匿名内部类是策略接口的实现)
     */
    @Test
    public void testEmpByInnerClass(){
        List<Emp> newEmps = null;
        //1、age >=35
//        newEmps = this.filterEmp(emps, new EmpFilterInterface<Emp>() {
//            @Override
//            public boolean test(Emp emp) {
//                return emp.getAge()>=35;
//            }
//        });

//        newEmps = this.filterEmp(emps, new EmpFilterInterface<Emp>() {
//            @Override
//            public boolean test(Emp emp) {
//                return emp.getAge()<35;
//            }
//        });

        newEmps = this.filterEmp(emps, new EmpFilterInterface<Emp>() {
            @Override
            public boolean test(Emp emp) {
                return emp.getSalary()>5000;
            }
        });

        for (Emp newEmp : newEmps) {
            System.out.println(newEmp);
        }
    }

    /**
     * 测试业务方法：客户端调用时通过 lambda 表达式优化(还是调用策略接口)
     */
    @Test
    public void testEmpLambda(){
        List<Emp> newEmps = null;
        //1、age>=35
//        newEmps = this.filterEmp(emps , emp -> emp.getAge()>=35);
        //2、
//        newEmps = this.filterEmp(emps , emp -> {
//            return emp.getAge() < 35;
//        });
        //3、
        newEmps = this.filterEmp(emps , emp -> emp.getSalary()>5000);

        for (Emp newEmp : newEmps) {
            System.out.println(newEmp);
        }
    }

    /**
     * 测试业务方法：只需要提供emps（集合数据）、Emp（实体类）,然后通过jdk1.8的Stream API方式
     */
    @Test
    public void testEmpByStream() {
        emps.stream()
                .filter((e) -> e.getSalary() >5000)
                //.limit(1) //只取集合中第一个数据
                .forEach(System.out::println);

        System.out.println("-----------筛选姓名-------------");
        emps.stream()
                .map(Emp::getName)
                .forEach(System.out::println);
    }

}
